<?php
namespace app\index\controller;

use think\Db;
use think\facade\Cache;
use think\facade\Lang;
use think\Facade\Env;

class Share extends Base
{
    private $mchid = 1431409102;
    private $appid = 'wxf84e37db2e7be7e0';
    private $appKey = '259426a9459f296ffcab671f5da73844';
    private $apiKey = 'gdb1yba0thwxmcsp5sf2bbkb4lz4e1t2';
    private $appurl = 'http://op.card.kdk23.top/test/';

    protected function initialize()
    {
        parent::initialize();
        $this->mchid =  Env::get('wx.mchid');
        $this->apiKey =  Env::get('wx.key');
        $this->appid =  Env::get('wx.appid');
        $this->appKey =  Env::get('wx.appSecret');
    }


    public function return_json($code = 1,$msg = 'ok',$data = '',$url= ''){
        return json([
            'status' => $code,
            'msg'    => $msg,
            'url'    => $url,
            'data'   => $data
        ]);
    }

    public function test(){ }

    //提交用户信息，创建支付订单，成功返回收银台地址
    public function uporder(){
        if($this->request->isPost()){
            //提交订单
            $data = $this->request->post();
            $order_id = uniqid();     //商品订单号
            if (empty($data['amount'])||floatval($data['amount'])<=0){
                return $this->sendFail("参数错误");
            }
            if (empty($data['order_name'])){
                return $this->sendFail("商品名字");
            }
            if (empty($data['mobile'])){
                return $this->sendFail("手机号");
            }
            if (empty($data['goods_id'])||intval($data['goods_id'])<=0){
                return $this->sendFail("goods_id");
            }
            if (empty($data['plan_id'])||intval($data['plan_id'])<=0){
                return $this->sendFail("plan_id");
            }
            if (empty($data['tariff_id'])||intval($data['plan_id'])<=0){
                return $this->sendFail("tariff_id");
            }
            if (empty($data['sms_code'])){
                return  $this->sendFail("sms_code");
            }
            if (empty($data['card'])){
                return  $this->sendFail("card");
            }
            if (empty($data['pass'])){
                return  $this->sendFail("pass");
            }
            $cardGood= Db::table('tb_card_good')->where("good_id",$data['goods_id'])->where("plan",$data['plan_id'])->find();
            if (!$cardGood){
                return  $this->sendFail("商品不存在");
            }
            $data['amount'] = $cardGood["money"];
            $card=   $data['card'];
            $pass=   $data['pass'];
            $info= Db::table('tb_card_info')->where("card",$card)->find();
            if ($info){
                if ($pass&&$pass!=$info["pass"]){
                    return  $this->sendFail("卡号校验失败");
                }
                if ($info["status"]==1){
                    return  $this->sendFail("卡号已使用");
                }

            }else{
                return  $this->sendFail("卡号不存在");
            }

            $sqlData=[];
            $sqlData["status"]=1;
            $res = Db::table('tb_card_info')->where("card",$card)->update($sqlData);
            if (!$res){
                return  $this->sendFail("卡号更新失败");
            }
            $data['status'] = -1;
            $data['order_id'] = $order_id;
            $data['create_time'] = time();

            Db::table('tb_order')->insert($data);
            return json([
                'status' => 1,
                'msg'    => 'ok',
                'data'    => $order_id,
                'sql'=> Db::table('tb_order')->getLastSql(),
                'url'   => $this->appurl . 'order.html?order_id=' . $order_id
            ]);
        }

    }

    //通过订单号判断订单是否存在，用户是否登陆
    public function users(){
        $order_id = input('order_id');
        $orders = Db::table('tb_order')->where('order_id',$order_id)->find();
        if(empty($orders)) {
            return $this->return_json('-2','订单不存在');
        }
        if (!$orders['openid']) {
            return $this->return_json('-1','登录失败');
        }
        return $this->return_json('1','',$orders);
    }

    //用户授权
    public function auth(){
        $order_id = input('orderId');
        $direct_url = explode('direct_url/', 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']);
        $direct_url = $direct_url[1];
        //微信授权
        $openid = $this->GetOpenid();
        $orders = Db::table('tb_order')->where('order_id',$order_id)->find();
        if(empty($orders['openid'])){
            Db::table('tb_order')->where('order_id',$order_id)->update(array('openid'=>$openid));
        }
        header("location:$direct_url");
        exit;
    }

    //用户支付
    public function pay(){
        $order_id = input('order_id');
        $orders = Db::table('tb_order')->where('order_id',$order_id)->find();
        if(empty($orders)) {
            echo json_encode(array('status' => -2, 'message' => '订单不存在!'));
            exit();
        }
        $payAmount = $orders['amount'];
        $orderName = $orders['order_name'];  //商品描述
        $outTradeNo = $order_id;
        $openId = $orders['openid'];
        $payTime = time();
        $notifyUrl = (self::is_https() ? 'https://' : 'http://').$_SERVER['HTTP_HOST'].'/share/notify';     //付款成功后的回调地址
        $jsApiParameters = $this->createJsBizPackage($payAmount,$orderName,$notifyUrl,$openId,$outTradeNo,$payTime);
        $data = array('jsApiParameters' => $jsApiParameters);
        echo json_encode(array('status' => 1, 'data' => $data));
        exit();
    }

    //支付成功调取订单成功信息
    public function order_detailed(){
        $order_id = input('order_id');
        $orders = Db::table('tb_order')->where('order_id',$order_id)->find();
        if(empty($orders)) {
            echo json_encode(array('status' => -2, 'message' => '订单不存在!'.Db::table('tb_order')->getLastSql()));
            exit();
        }
        echo json_encode(array('status' => 1, 'data' => $orders));
        exit();
    }

    //支付回调
    public function notify(){
        $arr = isset($GLOBALS['HTTP_RAW_POST_DATA']) ? $GLOBALS['HTTP_RAW_POST_DATA'] : '';
        if(empty($arr)) $arr = file_get_contents("php://input");
        if(empty($arr)) $arr = input();
        if (!empty($arr)){
            self::applog('pay',$arr);
            $arr = self::xmltoarr($arr);
            $ordersn = $arr['out_trade_no'];
            if ($arr['result_code'] === 'SUCCESS'){
                Db::table('tb_order')->where('order_id',$ordersn)->update(array('status'=>0,'pay_status'=>1,'pay_time'=>time()));
                echo self::array_to_xml([
                    'return_code'=> 'SUCCESS',
                    'return_msg'=> 'OK',
                ]);die;
            }
        }
    }


    public function createJsBizPackage($payAmount = 0.01,$orderName = '',$notifyUrl = '',$openid ,$outTradeNo,$payTime){
        $unified = array(
            'appid' => $this->appid,
            'attach' => 'pay',
            'body' => $orderName,
            'mch_id' => $this->mchid,
            'nonce_str' => self::createNonceStr(),
            'notify_url' => $notifyUrl,
            'openid' => $openid,
            'out_trade_no' => $outTradeNo,
            'spbill_create_ip' => self::get_client_ip(),
            'total_fee' => intval($payAmount * 100),       //单位 转为分
            'trade_type' => 'JSAPI',
        );
        $unified['sign'] = self::getSign($unified, $this->apiKey);
        $responseXml = self::curlPost('https://api.mch.weixin.qq.com/pay/unifiedorder', self::arrayToXml($unified));
        //禁止引用外部xml实体
        libxml_disable_entity_loader(true);
        $unifiedOrder = simplexml_load_string($responseXml, 'SimpleXMLElement', LIBXML_NOCDATA);
        if ($unifiedOrder === false) {
            echo json_encode(array('code' => -1, 'message' =>'parse xml error'));
            exit();
        }
        if ($unifiedOrder->return_code != 'SUCCESS') {
            echo json_encode(array('code' => -1, 'message' => $unifiedOrder->return_msg));
            exit();
        }
        if ($unifiedOrder->result_code != 'SUCCESS') {
            echo json_encode(array('code' => -1, 'message' => $unifiedOrder->err_code));
            exit();
        }
        $arr = array(
            "appId" => $this->appid,
            "timeStamp" => "$payTime",        //这里是字符串的时间戳，不是int，所以需加引号
            "nonceStr" => self::createNonceStr(),
            "package" => "prepay_id=" . $unifiedOrder->prepay_id,
            "signType" => 'MD5',
        );
        $arr['paySign'] = self::getSign($arr, $this->apiKey);
        return $arr;
    }
    public function GetOpenid()
    {
        //通过code获得openid
        if (!isset($_GET['code'])){
            //触发微信返回code码
            $scheme = self::is_https() ? 'https://' : 'http://';
            $uri = $_SERVER['PHP_SELF'].$_SERVER['QUERY_STRING'];
            if($_SERVER['REQUEST_URI']) $uri = $_SERVER['REQUEST_URI'];
            $baseUrl = urlencode($scheme.$_SERVER['HTTP_HOST'].$uri);
            $url = $this->CreateOauthUrlForCode($baseUrl);
            Header("Location: $url");
            exit();
        } else {
            //获取code码，以获取openid
            $code = $_GET['code'];
            $openid = $this->getOpenidFromMp($code);
            return $openid;
        }
    }
    private function GetOpenidFromMp($code)
    {
        $url = $this->CreateOauthUrlForOpenid($code);
        $res = self::curlGet($url);

        //取出openid
        $data = json_decode($res,true);
        $this->data = $data;
        $openid = $data['openid'];
        $access_token = $data['access_token'];

        $oauth2_url = "https://api.weixin.qq.com/sns/userinfo?access_token=$access_token&openid=$openid&lang=zh_CN";
        $content = self::curlGet($oauth2_url);
//        $json = file_get_contents($oauth2_url);//获取微信用户基本信息
//        $arr = json_decode($json,true);
//        var_dump($oauth2_url);
//        var_dump($arr);die;
        $info = @json_decode($content, true);
        $member = Db::table('tb_user')->where('openid',$openid)->find();
        if(empty($member)) {
            if(isset($info['nickname'])) {
                $info['nickname'] = preg_replace("/\\\u[ed][0-9a-f]{3}\\\u[ed][0-9a-f]{3}/", "*", $info['nickname']);//替换成*
            }
            $member = array(
                'openid' => $openid,
                'nickname' => isset($info['nickname']) ? $info['nickname'] : '',
                'headimgurl' => isset($info['headimgurl']) ? $info['headimgurl'] : '',
                'sex' => isset($info['sex']) ? $info['sex'] : '',
                'province' => isset($info['province']) ? $info['province'] : '',
                'city' => isset($info['city']) ? $info['city'] : '',
                'createtime' => time(),
            );
            Db::table('tb_user')->insert($member);
        }
        else{
            $upgrade = array();
            if (isset($info['nickname']) && $info['nickname'] != $member['nickname']) {
                $info['nickname'] = preg_replace("/\\\u[ed][0-9a-f]{3}\\\u[ed][0-9a-f]{3}/","*",$info['nickname']);//替换成*
                $upgrade['nickname'] = $info['nickname'];
            }
            if (isset($info['headimgurl']) && $info['headimgurl'] != $member['headimgurl']) {
                $upgrade['headimgurl'] = $info['headimgurl'];
            }
            if(!empty($upgrade)){
                Db::table('tb_user')->where('id' , $member['id'])->update($upgrade);
            }
        }
        return $openid;
    }
    private function CreateOauthUrlForCode($redirectUrl)
    {
        $urlObj["appid"] = $this->appid;
        $urlObj["redirect_uri"] = "$redirectUrl";
        $urlObj["response_type"] = "code";
        $urlObj["scope"] = "snsapi_base";  //静默授权的
        $urlObj["state"] = "STATE"."#wechat_redirect";
        $bizString = self::ToUrlParams($urlObj);
        return "https://open.weixin.qq.com/connect/oauth2/authorize?".$bizString;
    }
    private function CreateOauthUrlForOpenid($code)
    {
        $urlObj["appid"] = $this->appid;
        $urlObj["secret"] = $this->appKey;
        $urlObj["code"] = $code;
        $urlObj["grant_type"] = "authorization_code";
        $bizString = self::ToUrlParams($urlObj);
        return "https://api.weixin.qq.com/sns/oauth2/access_token?".$bizString;
    }
    private static function ToUrlParams($urlObj)
    {
        $buff = "";
        foreach ($urlObj as $k => $v)
        {
            if($k != "sign") $buff .= $k . "=" . $v . "&";
        }
        $buff = trim($buff, "&");
        return $buff;
    }
    private static function curlGet($url = '', $options = array())
    {
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        if (!empty($options)) {
            curl_setopt_array($ch, $options);
        }
        //https请求 不验证证书和host
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        $data = curl_exec($ch);
        curl_close($ch);
        return $data;
    }
    private static function curlPost($url = '', $postData = '', $options = array())
    {
        if (is_array($postData)) {
            $postData = http_build_query($postData);
        }
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30); //设置cURL允许执行的最长秒数
        if (!empty($options)) {
            curl_setopt_array($ch, $options);
        }
        //https请求 不验证证书和host
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        $data = curl_exec($ch);
        curl_close($ch);
        return $data;
    }
    private static function is_https() {
        if ( !empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off') {
            return true;
        } elseif ( isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https' ) {
            return true;
        } elseif ( !empty($_SERVER['HTTP_FRONT_END_HTTPS']) && strtolower($_SERVER['HTTP_FRONT_END_HTTPS']) !== 'off') {
            return true;
        }
        return false;
    }
    private static function createNonceStr($length = 16)
    {
        $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
        $str = '';
        for ($i = 0; $i < $length; $i++) {
            $str .= substr($chars, mt_rand(0, strlen($chars) - 1), 1);
        }
        return $str;
    }
    private static function getSign($params, $key)
    {
        ksort($params, SORT_STRING);
        $unSignParaString = self::formatQueryParaMap($params, false);
        $signStr = strtoupper(md5($unSignParaString . "&key=" . $key));
        return $signStr;
    }
    private static function formatQueryParaMap($paraMap, $urlEncode = false)
    {
        $buff = "";
        ksort($paraMap);
        foreach ($paraMap as $k => $v) {
            if (null != $v && "null" != $v) {
                if ($urlEncode) {
                    $v = urlencode($v);
                }
                $buff .= $k . "=" . $v . "&";
            }
        }
        $reqPar = '';
        if (strlen($buff) > 0) {
            $reqPar = substr($buff, 0, strlen($buff) - 1);
        }
        return $reqPar;
    }
    private static function arrayToXml($arr)
    {
        $xml = "<xml>";
        foreach ($arr as $key => $val) {
            if (is_numeric($val)) {
                $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
            } else
                $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
        }
        $xml .= "</xml>";
        return $xml;
    }
    private static function get_client_ip($type = 0,$adv=false) {
        $type       =  $type ? 1 : 0;
        static $ip  =   NULL;
        if ($ip !== NULL) return $ip[$type];
        if($adv){
            if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
                $arr    =   explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
                $pos    =   array_search('unknown',$arr);
                if(false !== $pos) unset($arr[$pos]);
                $ip     =   trim($arr[0]);
            }elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
                $ip     =   $_SERVER['HTTP_CLIENT_IP'];
            }elseif (isset($_SERVER['REMOTE_ADDR'])) {
                $ip     =   $_SERVER['REMOTE_ADDR'];
            }
        }elseif (isset($_SERVER['REMOTE_ADDR'])) {
            $ip     =   $_SERVER['REMOTE_ADDR'];
        }
        // IP地址合法验证
        $long = sprintf("%u",ip2long($ip));
        $ip   = $long ? array($ip, $long) : array('0.0.0.0', 0);
        return $ip[$type];
    }
    private static function applog($filename = 'log', $data) {
        $filepath = '../runtime/'.$filename.'/'.date('Y-m').'/';
        $name = date('Ymd').'_'.$filename.'.log';
        is_dir($filepath) or mkdir($filepath, 0777, true);
        file_put_contents($filepath.$name, $data, FILE_APPEND);
    }
    private static function xmltoarr($xml){//xml字符串转数组
        $array_data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
        return $array_data;
    }



}